home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS / lang / C / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-14  |  16.4 KB  |  804 lines  |  [TEXT/MPS ]

  1. /*
  2.  * proto
  3.  *
  4.  * function/variable prototyper.  Can dump just the symbols or
  5.  * symbols and types.  Can also dump out the symbol table for each
  6.  * scope (global, parameter, block-local).  Generates either K&R or
  7.  * ANSI function prototypes.
  8.  *
  9.  * Terence Parr
  10.  * Purdue University
  11.  * July 1991
  12.  * PCCTS Version 1.00
  13.  */
  14. #include <stdio.h>
  15. #if __STDC__ == 1
  16. #include <stdarg.h>
  17. #include <stdlib.h>
  18. #else
  19. #include <varargs.h>
  20. #include <malloc.h>
  21. #endif
  22. #include "stdpccts.h"
  23.  
  24. #define HashTableSize    999
  25. #define StringTableSize    10000
  26.  
  27. AST *root = NULL;
  28. Sym *Globals = NULL;
  29. Sym *Params = NULL;
  30. static int GenANSI = 0;
  31. static int GenVARS = 0;
  32. static int GenFUNCS = 0;
  33. static int JustSymbols = 0;
  34. static int GenKR_ANSI = 0;
  35. static int DumpScopes = 0;
  36. int PrintEngl = 0;
  37. static FILE *f;
  38.  
  39. char *decodeType();
  40.  
  41.  
  42.         /* C m d - L i n e  O p t i o n  S t r u c t  &  F u n c s */
  43.  
  44. typedef struct {
  45.             char *option;
  46.             int  arg;
  47.             void (*process)();
  48.             char *descr;
  49.         } Opt;
  50.  
  51. static void pANSI() { GenANSI = 1; }
  52. static void pVARS() { GenVARS = 1; }
  53. static void pFUNC() { GenFUNCS = 1; }
  54. static void pBoth() { GenKR_ANSI = 1; }
  55. static void pNAME() { JustSymbols = 1; }
  56. static void pSYM()  { DumpScopes = 1; }
  57. static void pENGL() { PrintEngl = 1; }
  58.  
  59. static void pFILE(s)
  60. char *s;
  61. {
  62.     f = fopen(s, "r");
  63.     if ( f == NULL )
  64.     {
  65.         fprintf(stderr, "file does not exist: %s\n", s);
  66.         help();
  67.         exit(-1);
  68.     }
  69. }
  70.  
  71. Opt options[] = {
  72.     { "-ansi", 0, pANSI,"Generate ANSI argument prototypes"},
  73.     { "-func", 0, pFUNC,"Generate extern defs for visible functions (default)"},
  74.     { "-both", 0, pBoth,"Generate K&R/ANSI func headers for all functions"},
  75.     { "-var", 0,  pVARS,"Generate extern defs for visible variables (default)"},
  76.     { "-name", 0, pNAME,"Generate visible symbols w/o types"},
  77.     { "-sym", 0,  pSYM, "Dump symbols for each scope"},
  78.     { "-engl", 0, pENGL,"Print english translation"},
  79.     { "*",   0,   pFILE,     "" },    /* anything else is a file */
  80.     { NULL, 0,    NULL, NULL }
  81. };
  82.  
  83. main(argc, argv)
  84. int argc;
  85. char **argv;
  86. {
  87.     f = stdin;
  88.     if ( argc != 1 ) ProcessArgs(argc-1, &(argv[1]), options);
  89.  
  90.     zzs_init(HashTableSize, StringTableSize);
  91.     ANTLR(globals(&root), f);
  92.     zzs_done();
  93.  
  94.     fclose( f ) ;
  95. }
  96.  
  97. pScope(p, s)
  98. Sym *p;
  99. char *s;
  100. {
  101.     if ( p == NULL || !DumpScopes ) return;
  102.     printf("%s", s);
  103.     for (; p!=NULL; p=p->scope)
  104.     {
  105.         printf("Level %02d | %-12s | %-15s",
  106.             p->level,
  107.             zztokens[p->token],
  108.             p->symbol);
  109.         if ( p->token == Var ||
  110.              p->token == Func ||
  111.              p->token == TypeName )
  112.         {
  113.             pType( p->type, NULL );
  114.         }
  115.         printf("\n");
  116.     }
  117. }
  118.  
  119. /*
  120.  * handleSymbol()
  121.  *
  122.  * Description        process the installation of symbols into the symbol
  123.  *                    table.  We handle:
  124.  *                        extern decls followed by the actual
  125.  *                            definitions.  
  126.  *                        typedefs
  127.  *                        function decls/defs (external and definition)
  128.  *                        old-style argument definitions
  129.  *
  130.  * Parameters
  131.  *        sc            storage class of symbol
  132.  *        symbol        symbol to handle
  133.  *        type        type of symbol
  134.  *        init        initialization expression-tree
  135.  *        level        level number (scope)
  136.  *
  137.  * Returns
  138.  *        nothing
  139.  */
  140. handleSymbol(sc, symbol, type, init, level)
  141. int sc;
  142. char *symbol;
  143. AST *type, *init;
  144. int level;
  145. {
  146.     AST *base;
  147.     Sym *n;
  148.  
  149.     /* T y p e d e f
  150.      *
  151.      * typedefs are added immediately in rule declarator and friends
  152.      * so we simply set the level and type here
  153.      */
  154.     if ( sc&scTypedef )
  155.     {
  156.         n = zzs_get(symbol);
  157.         n->level = level;
  158.         n->type = type;
  159.         return;
  160.     }
  161.  
  162.     n = zzs_get(symbol);
  163.  
  164.     /* F u n c t i o n
  165.      *
  166.      * The first extern func declaration is added to the symbol table
  167.      * any subsequent extern decls are ignored.  When an actual definition
  168.      * is seen, we set the 'defined' field in symbol table.
  169.      * If the function has not been seen before, add it to the symbol
  170.      * table.  Set the defined flag if not scExtern.
  171.      */
  172.     if ( type->nodeType == FunctionQ )
  173.     {
  174.         if ( n!=NULL )                            /* then defined already */
  175.         {
  176.             if ( !n->defined )                    /* was extern, now define */
  177.             {
  178.                 if ( !(sc&scExtern) )            /* do we have a def or decl */
  179.                 {
  180.                     n = addsym(Func, symbol, level, type, init);
  181.                     n->defined = 1;
  182.                 }
  183.                 return;
  184.             }
  185.             error1("function redefinition", symbol);
  186.         }
  187.         n = addsym(Func, symbol, level, type, init);
  188.         if ( !(sc&scExtern) )                    /* do we have a def or decl */
  189.         {
  190.             n->defined = 1;
  191.         }
  192.         return;
  193.     }
  194.  
  195.     /* V a r i a b l e
  196.      *
  197.      * If var has been seen before, check for redefinition.  If declared
  198.      * before and this is a definition, set 'defined' flag.  Ignore decls
  199.      * after first one.
  200.      *
  201.      * If level is parameter, we are adding old-style parameters.  The
  202.      * args rule will have added the symbols to the symbol table.
  203.      */
  204.     if ( n != NULL )                /* have we seen it before? */
  205.     {
  206.         if ( level == PARAMETER )    /* set type of parameter */
  207.         {
  208.             if ( n->defined ) error1("redefinition of parameter", symbol);
  209.             n->type = type;
  210.             n->defined = 1;
  211.             return;
  212.         }
  213.         /* if not a variable, we must make new variable entry in sym tab */
  214.         if ( n->token != Var )
  215.         {
  216.             n = addsym(Var, symbol, level, type, init);
  217.             if ( !(sc&scExtern) ) n->defined = 1;
  218.             return;
  219.         }
  220.         if ( !n->defined )            /* was it defined? */
  221.         {
  222.             if ( !(sc&scExtern) )    /* is this a def? */
  223.             {
  224.                 base = bottom(n->type);
  225.                 base->data.t.sc &= ~scExtern;
  226.                 n->defined = 1;
  227.             }
  228.             return;
  229.         }
  230.         if ( sc&scExtern )            /* redefinition? */
  231.             error1("redefinition of variable", symbol);
  232.         return;
  233.     }
  234.     if ( level == PARAMETER )        /* no parameter for this def */
  235.     {
  236.         error1("extraneous parameter declaration ignored", symbol);
  237.         return;
  238.     }
  239.     n = addsym(Var, symbol, level, type, init);
  240.     if ( !(sc&scExtern) ) n->defined = 1;
  241. }
  242.  
  243. /*
  244.  * Given a list of all 'extern' scope variables, dump an 'extern' def
  245.  * for just the variables that are visible outside the file (non-static).
  246.  */
  247. ProtoVars(globals)
  248. Sym *globals;
  249. {
  250.     Sym *p = globals;
  251.     AST *base;
  252.  
  253.     if ( globals == NULL || !GenVARS ) return;
  254.     for (; p!=NULL; p=p->scope)
  255.     {
  256.         if ( p->token == Var )
  257.         {
  258.             base = bottom(p->type);
  259.             if ( base == NULL ) continue;
  260.             if ( base->nodeType!=BaseTypeQ ) continue;
  261.             if ( !(base->data.t.sc&scStatic) &&
  262.                  !(base->data.t.sc&scExtern) )
  263.             {
  264.                 if ( JustSymbols ) printf("%s\n", p->symbol);
  265.                 else
  266.                 {
  267.                     printf("extern");
  268.                     pType(p->type, p->symbol);
  269.                     printf(";\n");
  270.                 }
  271.             }
  272.         }
  273.     }
  274. }
  275.  
  276. Proto(symbol, type)
  277. char *symbol;
  278. AST *type;
  279. {
  280.     if ( type == NULL || !GenFUNCS ) return;
  281.     if ( bottom(type)->data.t.sc&scStatic ) return;
  282.     if ( JustSymbols ) {printf("%s\n", symbol); return;}
  283.     printf("extern");
  284.     pType( zzchild(type), NULL ); /* dump return type ignoring first () */
  285.     printf(" %s(", symbol);
  286.     if ( GenANSI )
  287.     {
  288.         AST *a;
  289.  
  290.         if ( zzsibling(type)!=NULL )
  291.         {
  292.             for (a=zzsibling(type); a!=NULL; a = zzsibling(a))
  293.             {
  294.                 if ( a->nodeType == SymQ )
  295.                 {
  296.                     if ( zzchild(a)!=NULL )
  297.                         pType(zzchild(a), NULL);
  298.                     else
  299.                     {
  300.                         Sym *n = zzs_get(a->data.s.name);
  301.                         printf(" %s", a->data.s.name);
  302.                     }
  303.                 }
  304.                 else pType(a, NULL);    /* assume ,... here */
  305.                 if ( zzsibling(a) != NULL ) printf(",");
  306.             }
  307.         }
  308.         else
  309.             printf(" void");
  310.     }
  311.     printf(" );\n");
  312. }
  313.  
  314. /* Generate prototypes (w/o extern) that compile under both K&R and ANSI */
  315. ProtoBoth(symbol, type)
  316. char *symbol;
  317. AST *type;
  318. {
  319.     AST *a;
  320.  
  321.     if ( type == NULL || !GenKR_ANSI ) return;
  322. /*    if ( bottom(type)->data.t.sc&scStatic ) return; <-- do statics also */
  323.     pType( zzchild(type), NULL ); /* dump return type ignoring first () */
  324.     printf("\n#ifdef __STDC__\n");
  325.     printf("%s(", symbol);
  326.  
  327.     if ( zzsibling(type)!=NULL )
  328.     {
  329.         for (a=zzsibling(type); a!=NULL; a = zzsibling(a))
  330.         {
  331.             if ( a->nodeType == SymQ )
  332.             {
  333.                 if ( zzchild(a)!=NULL )
  334.                 {
  335.                     pType(zzchild(a), a->data.s.name);
  336.                 }
  337.                 else
  338.                 {
  339.                     Sym *n = zzs_get(a->data.s.name);    /* look up arg for type */
  340.                     if ( n==NULL )
  341.                         fprintf(stderr, "symbol table error: can't find parameter\n");
  342.                     else
  343.                     {
  344.                         pType(n->type, n->symbol);
  345.                     }
  346.                 }
  347.             }
  348.             else pType(a, NULL);    /* assume ,... here */
  349.             if ( zzsibling(a) != NULL ) printf(",");
  350.         }
  351.     }
  352.     else
  353.         printf(" void");
  354.  
  355.     printf(" )\n");
  356.  
  357.     printf("#else\n");
  358.  
  359.     printf("%s(", symbol);
  360.     if ( zzsibling(type)!=NULL )
  361.     {
  362.         for (a=zzsibling(type); a!=NULL; a = zzsibling(a))
  363.         {
  364.             if ( a->nodeType == SymQ )
  365.             {
  366.                 printf(" %s", a->data.s.name);
  367.             }
  368.             if ( zzsibling(a) != NULL && !(zzsibling(a)->nodeType == BaseTypeQ &&
  369.                  zzsibling(a)->data.t.type == tEllipsis) )
  370.                 printf(",");
  371.         }
  372.         printf(" )\n");
  373.         for (a=zzsibling(type); a!=NULL; a = zzsibling(a))
  374.         {
  375.             if ( a->nodeType == SymQ )
  376.             {
  377.                 if ( zzchild(a)!=NULL )
  378.                 {
  379.                     pType(zzchild(a), a->data.s.name);
  380.                 }
  381.                 else
  382.                 {
  383.                     Sym *n = zzs_get(a->data.s.name);    /* look up arg for type */
  384.                     if ( n==NULL )
  385.                         fprintf(stderr, "symbol table error: can't find parameter\n");
  386.                     else
  387.                     {
  388.                         pType(n->type, n->symbol);
  389.                     }
  390.                 }
  391.                 printf(";\n");
  392.             }
  393.         }
  394.     }
  395.     else
  396.         printf(" )\n");
  397.  
  398.  
  399.     printf("#endif\n\n");
  400. }
  401.  
  402. pArgs( args, comma )
  403. Sym *args;
  404. int comma;
  405. {
  406.     if ( args == NULL ) return;
  407.     pArgs( args->scope, 1 );    /* print the next one first, then this one */
  408.     pType( args->type, NULL );
  409.     if ( comma ) printf(",");
  410. }
  411.  
  412. pType(p, symbol)
  413. AST *p;
  414. char *symbol;
  415. {
  416.     char temp[500], out[500], *s;
  417.  
  418.     temp[0] = out[0] = '\0';
  419.     if ( symbol != NULL ) strcpy(out, symbol);
  420.     while ( p!=NULL )
  421.     {
  422.         switch ( p->nodeType )
  423.         {
  424.             case BaseTypeQ :
  425.                 s = decodeType(&p->data.t);
  426.                 if ( out[0] == '\0' ) sprintf(temp, "%s", s);
  427.                 else sprintf(temp, "%s %s", s, out);
  428.                 strcpy(out, temp);
  429.                 break;
  430.             case PointerQ :
  431.                 temp[0] = '\0';
  432.                 if ( p->down->nodeType == ArrayQ ||
  433.                      p->down->nodeType == FunctionQ )
  434.                 {
  435.                     strcpy(temp, "(");
  436.                 }
  437.                 if ( p->data.p.cv&cvConst )
  438.                     strcat(temp, "* constant");
  439.                 else if ( p->data.p.cv&cvVolatile )
  440.                     strcat(temp, "* volatile");
  441.                 else
  442.                     strcat(temp, "*");
  443.                 strcat(temp, out);
  444.                 if ( p->down->nodeType == ArrayQ ||
  445.                      p->down->nodeType == FunctionQ )
  446.                 {
  447.                     strcat(temp, ")");
  448.                 }
  449.                 strcpy(out, temp);
  450.                 break;
  451.             case ArrayQ :
  452.                 strcat(out, "[]");
  453.                 break;
  454.             case FunctionQ :
  455.                 strcat(out, "()");
  456.                 break;
  457.             default :
  458.                 fprintf(stderr, "pType: illegal nodetype\n");
  459.                 exit(-1);
  460.         }
  461.         p = p->down;
  462.     }
  463.     printf("%s", out);
  464. }
  465.  
  466. char *
  467. decodeType(base)
  468. qBaseType *base;
  469. {
  470.     static char temp[255], temp2[255];
  471.  
  472.     temp[0]=temp2[0]='\0';
  473.     if ( base->sc&scAuto )        strcat(temp," auto");
  474.     if ( base->sc&scRegister )    strcat(temp," register");
  475.     if ( base->sc&scStatic )    strcat(temp," static");
  476.     if ( base->sc&scExtern )    strcat(temp," extern");
  477.  
  478.     if ( base->cv&cvConst )        strcat(temp," constant");
  479.     if ( base->cv&cvVolatile )    strcat(temp," volatile");
  480.  
  481.     if ( base->type&tSigned )    strcat(temp," signed");
  482.     if ( base->type&tUnsigned)    strcat(temp," unsigned");
  483.     if ( base->type&tShort )    strcat(temp," short");
  484.     if ( base->type&tLong )        strcat(temp," long");
  485.     if ( base->type&tDouble )    strcat(temp," double");
  486.     if ( base->type&tInt )        strcat(temp," int");
  487.     if ( base->type&tFloat )    strcat(temp," float");
  488.     if ( base->type&tChar )        strcat(temp," char");
  489.     if ( base->type&tVoid )        strcat(temp," void");
  490.     if ( base->type&tEllipsis)    strcat(temp," ...");
  491.     if ( base->type&tUnion )
  492.     {
  493.         sprintf(temp2, " union %s",base->name!=NULL?base->name:"");
  494.         strcat(temp, temp2);
  495.     }
  496.     if ( base->type&tStruct)
  497.     {
  498.         sprintf(temp2, " struct %s",base->name!=NULL?base->name:"");
  499.         strcat(temp, temp2);
  500.     }
  501.     if ( base->type&tEnum )
  502.     {
  503.         sprintf(temp2, " union %s",base->name!=NULL?base->name:"");
  504.         strcat(temp, temp2);
  505.     }
  506.     if ( base->type&tTypeName)
  507.     {
  508.         sprintf(temp2, " %s",base->name);
  509.         strcat(temp, temp2);
  510.     }
  511.     return temp;
  512. }
  513.  
  514. /* Constructor for AST nodes
  515.  * First parameter is always pointer to newly-created AST node
  516.  * Second is the AST node type which will tell us what follows
  517.  * on the stack.
  518.  */
  519.  
  520. #ifdef __STDC__
  521. AST *zzmk_ast(AST *t, int nt, ...)
  522. #else
  523. AST *zzmk_ast(va_alist)
  524. va_dcl
  525. #endif
  526. {
  527. #ifndef __STDC__
  528.     int nt;
  529.     AST *t;
  530. #endif
  531.     va_list ap;
  532.  
  533. #ifdef __STDC__
  534.     va_start(ap, nt);
  535. #else
  536.     va_start(ap);
  537.     t = va_arg(ap, AST *);
  538.     nt = va_arg(ap, int);
  539. #endif
  540.  
  541.     t->nodeType = nt;
  542.     switch ( t->nodeType )
  543.     {
  544.         case BaseTypeQ :
  545.             t->data.t.cv = va_arg(ap, int);
  546.             t->data.t.sc = va_arg(ap, int);
  547.             t->data.t.type = va_arg(ap, int);
  548.             t->data.t.name = mystrdup( va_arg(ap, char *) );
  549.             break;
  550.         case PointerQ :
  551.             t->data.p.cv = va_arg(ap, int);
  552.             break;
  553.         case ArrayQ :
  554.             t->data.a.dim = va_arg(ap, AST *);
  555.             break;
  556.         case FunctionQ :
  557.             break;
  558.         case FieldQ :
  559.             t->data.fi.name = mystrdup( va_arg(ap, char *) );
  560.             break;
  561.         case SymQ :
  562.             t->data.s.name = mystrdup( va_arg(ap, char *) );
  563.             t->data.s.init = va_arg(ap, AST *);
  564.             break;
  565.         case ENode :
  566.             t->data.e.token = va_arg(ap, int);
  567.             break;
  568.         default :
  569.             fprintf(stderr, "zzmk_ast: illegal nodetype\n");
  570.             exit(-1);
  571.     }
  572.  
  573.     va_end(ap);
  574.     return t;
  575. }
  576.  
  577. void
  578. fatal(s)
  579. char *s;
  580. {
  581.     error(s);
  582.     exit(-1);
  583. }
  584.  
  585. void
  586. error(s)
  587. char *s;
  588. {
  589.     fprintf(stderr, "line %d, error: %s\n", zzline, s);
  590. }
  591.  
  592. void
  593. warn(s)
  594. char *s;
  595. {
  596.     fprintf(stderr, "line %d, warning: %s\n", zzline, s);
  597. }
  598.  
  599. void
  600. error1(s, s2)
  601. char *s, *s2;
  602. {
  603.     fprintf(stderr, "line %d, error: %s: %s\n", zzline, s, s2);
  604. }
  605.  
  606. void
  607. warn1(s, s2)
  608. char *s, *s2;
  609. {
  610.     fprintf(stderr, "line %d, warning: %s: %s\n", zzline, s, s2);
  611. }
  612.  
  613. /* scan the declarator tree for the FunctionQ node.  If there
  614.  * are any arguments, add them to the symbol table for parameters
  615.  * using the scope passed in.
  616.  *
  617.  * The arguments are siblings of the FunctionQ node in the type
  618.  * tree.  e.g.
  619.  *
  620.  *        ...
  621.  *         |
  622.  *         v
  623.  *    [FunctionQ]-->[arg1]--> ... -->[argn]
  624.  *         |            |                 |
  625.  *         v            v                 v
  626.  *        ...         [type1]          [type1]
  627.  *
  628.  * Check for inconsistent definitions.
  629.  *
  630.  * Return a pointer to the first argument (NULL if there is none)
  631.  * Also, return NULL if new-style arguments are found since
  632.  * we won't need to check them later.
  633.  */
  634. AST *
  635. defineArgs(a, scope)
  636. AST *a;
  637. Sym **scope;
  638. {
  639.     Sym **save = zzs_scope( NULL );
  640.     AST *b, *args;
  641.     int which = 0;    /* 1 implies old-style, 2 implies new-style defs */
  642.  
  643.     while ( a != NULL )
  644.     {
  645.         if ( a->nodeType == FunctionQ ) break;
  646.         a = zzchild( a );
  647.     }
  648.     if ( a == NULL )        /* no parameters */
  649.     {
  650.         return NULL;
  651.     }
  652.  
  653.     zzs_scope( scope );
  654.     for (a=args=zzsibling(a); a != NULL; a = zzsibling(a))
  655.     {
  656.         if ( a->nodeType != SymQ )
  657.         {
  658.             if ( a->nodeType != BaseTypeQ ||
  659.                  (a->nodeType == BaseTypeQ&&a->data.t.type != tVoid &&
  660.                   a->nodeType == BaseTypeQ&&a->data.t.type != tEllipsis) )
  661.                 error("how about a name with that type?");
  662.         }
  663.         else if ( zzchild(a) != NULL )
  664.         {
  665.             for (b=zzchild(a); b!=NULL; b=zzchild(b))
  666.             {
  667.                 if ( b->nodeType == BaseTypeQ )        /* type & symbol */
  668.                 {
  669.                     if ( which == 1 )
  670.                         error("mixed old- and new-style parameter definitions");
  671.                     else {
  672.                         which = 2;    /* new-style definition */
  673.                         addsym(Var,
  674.                                a->data.s.name,
  675.                                PARAMETER,
  676.                                zzchild(a),
  677.                                NULL);
  678.                         args = NULL;
  679.                     }
  680.                     break;
  681.                 }
  682.             }
  683.         }
  684.         else            /* old-style parameter */
  685.         {
  686.             if ( which == 2 )
  687.                 error("mixed old- and new-style parameter definitions");
  688.             which = 1;
  689.             /* add parameter to symbol table.  Type is set later */
  690.             addsym(Var, a->data.s.name, PARAMETER, NULL, NULL);
  691.         }
  692.     }
  693.     zzs_scope( save );
  694.  
  695.     return args;
  696. }
  697.  
  698. /* Given a list of arguments from a function argument list, check to
  699.  * see that they are all in the symbol tables as parameters.
  700.  */
  701. checkArgs(args)
  702. AST *args;
  703. {
  704.     AST *a, *type;
  705.     Sym *p;
  706.  
  707.     for (a=args; a!=NULL; a=zzsibling(a))    /* for each argument */
  708.     {
  709.         if ( a->data.s.name == NULL ) continue;
  710.         p = zzs_get( a->data.s.name );
  711.         if ( p != NULL && !p->defined )
  712.             {
  713.                 warn1("you forgot to define parameter", a->data.s.name);
  714.                 type = zzastnew();
  715.                 zzmk_ast(type,BaseTypeQ,0,0,tInt,NULL);
  716.                 addsym(Var, a->data.s.name, PARAMETER, type, NULL);
  717.             }
  718.     }
  719. }
  720.  
  721. Sym *
  722. addsym(tok, symbol, level, type, init)
  723. int tok;
  724. char *symbol;
  725. int level;
  726. AST *type, *init;
  727. {
  728.     Sym *p = zzs_newadd(symbol);
  729.  
  730.     if ( p == NULL ) return NULL;
  731.     p->token = tok;
  732.     p->level = level;
  733.     p->type = type;
  734.     p->init = init;
  735.     return p;
  736. }
  737.  
  738. AST *bottom(t)
  739. AST *t;
  740. {
  741.     if ( t==NULL ) return NULL;
  742.     if ( t->down != NULL ) return bottom(t->down);
  743.     return t;
  744. }
  745.  
  746. char *
  747. mystrdup(s)
  748. char *s;
  749. {
  750.     char *p;
  751.     if ( s == NULL ) return NULL;
  752.     p = malloc(strlen(s)+1);
  753.     if ( p == NULL ) return NULL;
  754.     strcpy(p, s);
  755.     return p;
  756. }
  757.  
  758. help()
  759. {
  760.     Opt *p = options;
  761.     fprintf(stderr, "proto [options] file.c\n");
  762.     while ( *(p->option) != '*' )
  763.     {
  764.         fprintf(stderr, "\t%s %s\t%s\n",
  765.                         p->option,
  766.                         (p->arg)?"___":"   ",
  767.                         p->descr);
  768.         p++;
  769.     }
  770. }
  771.  
  772. ProcessArgs(argc, argv, options)
  773. int argc;
  774. char **argv;
  775. Opt *options;
  776. {
  777.     Opt *p;
  778.  
  779.     if ( argv==NULL ) return;
  780.     while ( argc-- > 0 )
  781.     {
  782.         p = options;
  783.         while ( p->option != NULL )
  784.         {
  785.             if ( strcmp(p->option, "*") == 0 ||
  786.                  strcmp(p->option, *argv) == 0 )
  787.             {
  788.                 if ( p->arg )
  789.                 {
  790.                     (*p->process)( *argv, *(argv+1) );
  791.                     argv++;
  792.                     argc--;
  793.                 }
  794.                 else
  795.                     (*p->process)( *argv );
  796.                 break;
  797.             }
  798.             p++;
  799.         }
  800.         argv++;
  801.     }
  802. }
  803.  
  804.